Skip to content

Commit 73cf920

Browse files
rayozziezfields
andauthored
feat: User Agent support (#56)
* add preliminary User Agent support * remove note-c before re-add * Squashed 'src/note-c/' content from commit fa5dca9 git-subtree-dir: src/note-c git-subtree-split: fa5dca95fcc84368fbad997df4b4b86274a67fbc * feat: User Agent Unit-tests Co-authored-by: Zachary J. Fields <[email protected]>
1 parent affe163 commit 73cf920

File tree

9 files changed

+493
-150
lines changed

9 files changed

+493
-150
lines changed

src/Notecard.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ Notecard::~Notecard (void)
190190
/**************************************************************************/
191191
void Notecard::begin(uint32_t i2caddress, uint32_t i2cmax, TwoWire &wirePort)
192192
{
193+
NoteSetUserAgent((char *)"note-arduino");
193194
NoteSetFnDefault(malloc, free, delay, millis);
194195
noteI2c = make_note_i2c(&wirePort);
195196

@@ -211,6 +212,7 @@ void Notecard::begin(uint32_t i2caddress, uint32_t i2cmax, TwoWire &wirePort)
211212
/**************************************************************************/
212213
void Notecard::begin(HardwareSerial &selectedSerialPort, int selectedSpeed)
213214
{
215+
NoteSetUserAgent((char *)"note-arduino");
214216
NoteSetFnDefault(malloc, free, delay, millis);
215217
noteSerial = make_note_serial(&selectedSerialPort, selectedSpeed);
216218

src/note-c/n_hooks.c

+23-6
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,23 @@ void NoteUnlockNote()
500500
}
501501
}
502502

503+
//**************************************************************************/
504+
/*!
505+
@brief Get the active interface's name
506+
@returns A string
507+
*/
508+
/**************************************************************************/
509+
const char *NoteActiveInterface()
510+
{
511+
switch (hookActiveInterface) {
512+
case interfaceSerial:
513+
return "serial";
514+
case interfaceI2C:
515+
return "i2c";
516+
}
517+
return "unknown";
518+
}
519+
503520
//**************************************************************************/
504521
/*!
505522
@brief Reset the Serial bus using the platform-specific hook.
@@ -618,8 +635,8 @@ const char *NoteI2CReceive(uint16_t DevAddress, uint8_t* pBuffer, uint16_t Size,
618635
/**************************************************************************/
619636
uint32_t NoteI2CAddress()
620637
{
621-
if (i2cAddress == NOTE_I2C_ADDR_DEFAULT) {
622-
return 0x17;
638+
if (i2cAddress == 0) {
639+
return NOTE_I2C_ADDR_DEFAULT;
623640
}
624641
return i2cAddress;
625642
}
@@ -646,12 +663,12 @@ uint32_t NoteI2CMax()
646663
{
647664
// Many Arduino libraries (such as ESP32) have a limit less than 32, so if the max isn't specified
648665
// we must assume the worst and segment the I2C messages into very tiny chunks.
649-
if (i2cMax == NOTE_I2C_MAX_DEFAULT) {
650-
return 30;
666+
if (i2cMax == 0) {
667+
return NOTE_I2C_MAX_DEFAULT;
651668
}
652669
// Note design specs
653-
if (i2cMax > 127) {
654-
i2cMax = 127;
670+
if (i2cMax > NOTE_I2C_MAX_MAX) {
671+
i2cMax = NOTE_I2C_MAX_MAX;
655672
}
656673
return i2cMax;
657674
}

src/note-c/n_lib.h

+1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ bool serialNoteReset(void);
8383
// Hooks
8484
void NoteLockNote(void);
8585
void NoteUnlockNote(void);
86+
const char *NoteActiveInterface(void);
8687
bool NoteSerialReset(void);
8788
void NoteSerialTransmit(uint8_t *, size_t, bool);
8889
bool NoteSerialAvailable(void);

src/note-c/n_request.c

+30-1
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,21 @@ char *NoteRequestResponseJSON(char *reqJSON)
312312

313313
}
314314

315+
/**************************************************************************/
316+
/*!
317+
@brief Override-able method to return user agent object
318+
@returns a `J` cJSON object with the user agent object.
319+
*/
320+
/**************************************************************************/
321+
#if defined(_MSC_VER)
322+
J *noteUserAgent()
323+
#else
324+
__attribute__((weak)) J *noteUserAgent()
325+
#endif
326+
{
327+
return NULL;
328+
}
329+
315330
/**************************************************************************/
316331
/*!
317332
@brief Initiate a transaction to the Notecard and return the response.
@@ -331,8 +346,22 @@ J *NoteTransaction(J *req)
331346
return NULL;
332347
}
333348

349+
// Determine the request or command type
350+
const char *reqType = JGetString(req, "req");
351+
const char *cmdType = JGetString(req, "cmd");
352+
353+
// Add the user agent object if appropriate
354+
#ifndef NOTE_DISABLE_USER_AGENT
355+
if (!JIsPresent(req, "body") && (strcmp(reqType, "hub.set") == 0 || strcmp(cmdType, "hub.set"))) {
356+
J *body = noteUserAgent();
357+
if (body != NULL) {
358+
JAddItemToObject(req, "body", body);
359+
}
360+
}
361+
#endif
362+
334363
// Determine whether or not a response will be expected, by virtue of "cmd" being present
335-
bool noResponseExpected = (JGetString(req, "req")[0] == '\0' && JGetString(req, "cmd")[0] != '\0');
364+
bool noResponseExpected = (reqType[0] == '\0' && cmdType[0] != '\0');
336365

337366
// If a reset of the module is required for any reason, do it now.
338367
// We must do this before acquiring lock.

src/note-c/n_ua.c

+186
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/*!
2+
* @file n_ua.c
3+
*
4+
* Written by Ray Ozzie and Blues Inc. team.
5+
*
6+
* Copyright (c) 2019 Blues Inc. MIT License. Use of this source code is
7+
* governed by licenses granted by the copyright holder including that found in
8+
* the
9+
* <a href="https://github.com/blues/note-c/blob/master/LICENSE">LICENSE</a>
10+
* file.
11+
*
12+
*/
13+
14+
#ifndef NOTE_LOWMEM
15+
16+
#include "n_lib.h"
17+
18+
// Override-able statics
19+
static char *n_agent = "note-c";
20+
static char *n_os_name = NULL;
21+
static char *n_os_platform = NULL;
22+
static char *n_os_family = NULL;
23+
static char *n_os_version = NULL;
24+
static int n_cpu_mem = 0;
25+
static int n_cpu_mhz = 0;
26+
static int n_cpu_cores = 0;
27+
static char *n_cpu_vendor = NULL;
28+
static char *n_cpu_name = NULL;
29+
30+
/**************************************************************************/
31+
/*!
32+
@brief Method to return user agent object
33+
@returns a `J` cJSON object with the user agent object.
34+
*/
35+
/**************************************************************************/
36+
J *noteUserAgent()
37+
{
38+
39+
J *ua = JCreateObject();
40+
if (ua == NULL) {
41+
return ua;
42+
}
43+
44+
#if defined(__cplusplus)
45+
#define PLUS " c++"
46+
#else
47+
#define PLUS ""
48+
#endif
49+
50+
#if defined(__ICCARM__)
51+
char *compiler = "iar arm" PLUS " " __VER__;
52+
#elif defined(__IAR_SYSTEMS_ICC__)
53+
char *compiler = "iar" PLUS " " __VER__;
54+
#elif defined(__clang__)
55+
char *compiler = "clang" PLUS " " __VERSION__;
56+
#elif defined(__GNUC__)
57+
char *compiler = "gcc" PLUS " " __VERSION__;
58+
#elif defined(__ATOLLIC__) && defined(__GNUC__)
59+
char *compiler = "atollic gcc" PLUS " " __VERSION__;
60+
#elif defined(_MSC_FULL_VER)
61+
char *compiler = "msc" PLUS " " _MSC_FULL_VER;
62+
#elif defined(__STDC_VERSION___)
63+
char *compiler = "STDC" PLUS " " __STDC_VERSION__;
64+
#else
65+
char *compiler = "unknown" PLUS " " __VERSION__
66+
#endif
67+
68+
#if defined(ARDUINO_ARCH_ARC32)
69+
char *arch = "arc32";
70+
#elif defined(ARDUINO_ARCH_AVR)
71+
char *arch = "avr";
72+
#elif defined(ARDUINO_ARCH_ESP32)
73+
char *arch = "esp32";
74+
#elif defined(ARDUINO_ARCH_ESP8266)
75+
char *arch = "esp8266";
76+
#elif defined(ARDUINO_ARCH_MBED)
77+
char *arch = "mbed";
78+
#elif defined(ARDUINO_ARCH_MEGAAVR)
79+
char *arch = "megaavr";
80+
#elif defined(ARDUINO_ARCH_NRF52840)
81+
char *arch = "nrf52840";
82+
#elif defined(ARDUINO_ARCH_NRF52)
83+
char *arch = "nrf52";
84+
#elif defined(ARDUINO_ARCH_NRF51)
85+
char *arch = "nrf51";
86+
#elif defined(ARDUINO_ARCH_PIC32)
87+
char *arch = "pic32";
88+
#elif defined(ARDUINO_ARCH_SAMD)
89+
char *arch = "samd";
90+
#elif defined(ARDUINO_ARCH_SAM)
91+
char *arch = "sam";
92+
#elif defined(ARDUINO_ARCH_SPRESENSE)
93+
char *arch = "spresence";
94+
#elif defined(ARDUINO_ARCH_STM32F0)
95+
char *arch = "stm32f0";
96+
#elif defined(ARDUINO_ARCH_STM32F1)
97+
char *arch = "stm32f1";
98+
#elif defined(ARDUINO_ARCH_STM32F4)
99+
char *arch = "stm32f4";
100+
#elif defined(ARDUINO_ARCH_STM32G0)
101+
char *arch = "stm32g0";
102+
#elif defined(ARDUINO_ARCH_STM32L4)
103+
char *arch = "stm32f4";
104+
#elif defined(ARDUINO_ARCH_STM32U5)
105+
char *arch = "stm32u5";
106+
#elif defined(ARDUINO_ARCH_STM32)
107+
char *arch = "stm32";
108+
#else
109+
char *arch = "";
110+
#endif
111+
112+
JAddStringToObject(ua, "agent", n_agent);
113+
JAddStringToObject(ua, "compiler", compiler);
114+
JAddStringToObject(ua, "req_interface", NoteActiveInterface());
115+
116+
if (n_cpu_mem != 0) {
117+
JAddNumberToObject(ua, "cpu_mem", n_cpu_mem);
118+
}
119+
if (n_cpu_mhz != 0) {
120+
JAddNumberToObject(ua, "cpu_mhz", n_cpu_mhz);
121+
}
122+
if (n_cpu_cores != 0) {
123+
JAddNumberToObject(ua, "cpu_cores", n_cpu_cores);
124+
}
125+
if (n_cpu_vendor != NULL) {
126+
JAddStringToObject(ua, "cpu_vendor", n_cpu_vendor);
127+
}
128+
if (n_cpu_name != NULL) {
129+
JAddStringToObject(ua, "cpu_name", n_cpu_name);
130+
}
131+
132+
if (n_os_name != NULL) {
133+
JAddStringToObject(ua, "os_name", n_os_name);
134+
}
135+
if (n_os_platform != NULL) {
136+
JAddStringToObject(ua, "os_platform", n_os_platform);
137+
}
138+
if (n_os_family != NULL) {
139+
JAddStringToObject(ua, "os_family", n_os_family);
140+
}
141+
if (n_os_version != NULL) {
142+
JAddStringToObject(ua, "os_version", n_os_version);
143+
}
144+
145+
return ua;
146+
147+
}
148+
149+
/**************************************************************************/
150+
/*!
151+
@brief Set key UA fields from a higher level library context
152+
*/
153+
/**************************************************************************/
154+
void NoteSetUserAgent(char *agent)
155+
{
156+
n_agent = agent;
157+
}
158+
159+
/**************************************************************************/
160+
/*!
161+
@brief Set key UA fields from a higher level library context
162+
*/
163+
/**************************************************************************/
164+
void NoteSetUserAgentOS(char *os_name, char *os_platform, char *os_family, char *os_version)
165+
{
166+
n_os_name = os_name;
167+
n_os_platform = os_platform;
168+
n_os_family = os_family;
169+
n_os_version = os_version;
170+
}
171+
172+
/**************************************************************************/
173+
/*!
174+
@brief Set key UA fields from a higher level library context
175+
*/
176+
/**************************************************************************/
177+
void NoteSetUserAgentCPU(int cpu_mem, int cpu_mhz, int cpu_cores, char *cpu_vendor, char *cpu_name)
178+
{
179+
n_cpu_mem = cpu_mem;
180+
n_cpu_mhz = cpu_mhz;
181+
n_cpu_cores = cpu_cores;
182+
n_cpu_vendor = cpu_vendor;
183+
n_cpu_name = cpu_name;
184+
}
185+
186+
#endif

src/note-c/note.h

+12-2
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,22 @@ void NoteSetFnMutex(mutexFn lockI2Cfn, mutexFn unlockI2Cfn, mutexFn lockNotefn,
126126
void NoteSetFnDefault(mallocFn mallocfn, freeFn freefn, delayMsFn delayfn, getMsFn millisfn);
127127
void NoteSetFn(mallocFn mallocfn, freeFn freefn, delayMsFn delayfn, getMsFn millisfn);
128128
void NoteSetFnSerial(serialResetFn resetfn, serialTransmitFn writefn, serialAvailableFn availfn, serialReceiveFn readfn);
129-
#define NOTE_I2C_ADDR_DEFAULT 0
130-
#define NOTE_I2C_MAX_DEFAULT 0
129+
#define NOTE_I2C_ADDR_DEFAULT 0x17
130+
#ifndef NOTE_I2C_MAX_DEFAULT
131+
#define NOTE_I2C_MAX_DEFAULT 30
132+
#endif
133+
#ifndef NOTE_I2C_MAX_MAX
134+
#define NOTE_I2C_MAX_MAX 127
135+
#endif
131136
void NoteSetFnI2C(uint32_t i2caddr, uint32_t i2cmax, i2cResetFn resetfn, i2cTransmitFn transmitfn, i2cReceiveFn receivefn);
132137
void NoteSetFnDisabled(void);
133138
void NoteSetI2CAddress(uint32_t i2caddress);
134139

140+
// User agent
141+
void NoteSetUserAgent(char *agent);
142+
void NoteSetUserAgentOS(char *os_name, char *os_platform, char *os_family, char *os_version);
143+
void NoteSetUserAgentCPU(int cpu_mem, int cpu_mhz, int cpu_cores, char *cpu_vendor, char *cpu_name);
144+
135145
// Calls to the functions set above
136146
void NoteDebug(const char *message);
137147
void NoteDebugln(const char *message);

0 commit comments

Comments
 (0)