Arduino-Redis
A Redis library for Arduino.
Redis.h
1 
21 #ifndef REDIS_H
22 #define REDIS_H
23 
24 #include "Arduino.h"
25 #include "Client.h"
26 
27 #include <vector>
28 
29 typedef enum {
30  RedisSuccess = 0,
31  RedisNotConnectedFailure = 1,
32  RedisAuthFailure = 2,
33 } RedisReturnValue;
34 
35 typedef enum {
36  RedisSubscribeBadCallback = -255,
37  RedisSubscribeSetupFailure,
38  RedisSubscribeSuccess = 0
39 } RedisSubscribeResult;
40 
41 typedef enum {
42  RedisMessageBadResponseType = -255,
43  RedisMessageTruncatedResponse,
44  RedisMessageUnknownType,
45 } RedisMessageError;
46 
55 class Redis {
56 public:
58  typedef void (*RedisMsgCallback)(Redis*, String channel, String message);
60  typedef void (*RedisMsgErrorCallback)(Redis*, RedisMessageError);
61 
67  Redis(Client& client) : conn(client) {}
68 
69  ~Redis() {}
70  Redis(const Redis&) = delete;
71  Redis& operator=(const Redis&) = delete;
72  Redis(const Redis&&) = delete;
73  Redis& operator=(const Redis&&) = delete;
74 
80  RedisReturnValue authenticate(const char* password);
81 
91  bool set(const char* key, const char* value);
92 
98  String get(const char* key);
99 
105  bool del(const char* key);
106 
112  bool exists(const char* key);
113 
120  int append(const char* key, const char* value);
121 
128  int publish(const char* channel, const char* message);
129 
136  bool expire(const char* key, int seconds) { return _expire_(key, seconds, "EXPIRE"); }
137 
145  bool expire_at(const char* key, int timestamp) { return _expire_(key, timestamp, "EXPIREAT"); }
146 
153  bool pexpire(const char* key, int ms) { return _expire_(key, ms, "PEXPIRE"); }
154 
162  bool pexpire_at(const char* key, int timestamp) { return _expire_(key, timestamp, "PEXPIREAT"); }
163 
169  bool persist(const char* key);
170 
177  int ttl(const char* key) { return _ttl_(key, "TTL"); }
178 
185  int pttl(const char* key) { return _ttl_(key, "PTTL"); }
186 
194  bool hset(const char* key, const char* field, const char* value) { return _hset_(key, field, value, "HSET"); }
195 
203  bool hsetnx(const char* key, const char* field, const char* value) { return _hset_(key, field, value, "HSETNX"); }
204 
211  String hget(const char* key, const char* field);
218  bool hdel(const char* key, const char* field);
219 
225  int hlen(const char* key);
226 
233  int hstrlen(const char* key, const char* field);
234 
241  bool hexists(const char* key, const char* field);
242 
249  std::vector<String> lrange(const char* key, int start, int stop);
250 
254  bool subscribe(const char* channel) { return _subscribe(SubscribeSpec{false, String(channel)}); }
255 
259  bool psubscribe(const char* pattern) { return _subscribe(SubscribeSpec{true, String(pattern)}); }
260 
264  bool unsubscribe(const char* channelOrPattern);
265 
275  RedisSubscribeResult startSubscribing(RedisMsgCallback messageCallback, RedisMsgErrorCallback errorCallback = nullptr);
276 
280  void stopSubscribing() { subLoopRun = false; }
281 
282 #if ARDUINO_REDIS_TEST
283  typedef struct {
284  int total;
285  int passed;
286  } TestResults;
287 
288  TestResults runTests(bool logToSerial = false,
289  String prefix = "__com.arduino-redis.test",
290  bool retainData = false);
291 #endif // ARDUINO_REDIS_TEST
292 
293 private:
294  typedef struct {
295  bool pattern;
296  String spec;
297  } SubscribeSpec;
298 
299  bool _subscribe(SubscribeSpec spec);
300 
301  Client& conn;
302  std::vector<SubscribeSpec> subSpec;
303  bool subscriberMode = false;
304  bool subLoopRun = false;
305 
306  bool _expire_(const char*, int, const char*);
307  int _ttl_(const char*, const char*);
308  bool _hset_(const char*, const char*, const char*, const char*);
309 };
310 
311 #if ARDUINO_REDIS_TEST
312 #include <map>
313 
314 /* tests are not expected to pass if retainData = true */
315 Redis::TestResults Redis::runTests(bool logToSerial, String prefix, bool retainData)
316 {
317  /* These are NOT executed in definition order! */
318  std::map<String, std::function<bool(const char*)>> g_Tests
319  {
320  { "set", [this](const char* k) { return set(k, "!"); } },
321  { "setget", [this](const char* k) { return set(k, "!") == 1 && get(k) == "!"; } },
322  { "expire", [this](const char* k) {
323  return set(k, "E") && expire(k, 5) && ttl(k) > 4;
324  } },
325  { "pexpire", [this](const char* k) {
326  return set(k, "PE") && pexpire(k, 5000) && pttl(k) > 4500;
327  } },
328  { "dlyexp", [this](const char* k) {
329  auto sr = set(k, "DE");
330  expire(k, 10);
331  delay(4000);
332  auto t = ttl(k);
333  return sr && t > 5 && t < 7;
334  } },
335  { "hset", [this](const char* k) { return hset(k, "TF", "H!") && hexists(k, "TF"); } },
336  { "hsetget", [this](const char* k) {
337  return hset(k, "TF", "HH") && hget(k, "TF") == "HH";
338  } },
339  { "hlen", [this](const char* k) {
340  for (int i = 0; i < 10; i++) {
341  auto fv = String(i);
342  hset(k, String("field-" + fv).c_str(), fv.c_str());
343  }
344  return hlen(k) == 10;
345  } },
346  { "hstrlen", [this](const char* k) {
347  return hset(k, "hsr", k) && hstrlen(k, "hsr") == strlen(k);
348  } },
349  { "append", [this](const char* k) { return append(k, "foo") == 3; } },
350  { "exists", [this](const char* k) { return set(k, k) && exists(k); } }
351  };
352 
353  if (logToSerial) {
354  Serial.begin(115200);
355  Serial.printf("Redis::run_tests(\"%s\") starting...\n", prefix.c_str());
356  }
357 
358  auto pFunc = [&prefix](const String& n) { return String(prefix + "." + n); };
359 
360  int total = 0, pass = 0;
361  for (auto& kv : g_Tests)
362  {
363  auto tName = kv.first;
364  auto tFunc = kv.second;
365  auto pName = pFunc(tName);
366  auto tRes = tFunc(pName.c_str());
367  if (logToSerial)
368  Serial.printf("\tTest \"%s\":\t%s\n", tName.c_str(), tRes ? "pass" : "FAIL");
369  total++;
370  pass += tRes ? 1 : 0;
371  }
372 
373  if (logToSerial)
374  Serial.printf("Result: %d passed / %d total\n", pass, total);
375 
376  if (!retainData)
377  for (auto& kv : g_Tests)
378  (void)del(pFunc(kv.first).c_str());
379 
380  return { .total = total, .passed = pass };
381 }
382 #endif
383 
384 #endif
Redis::ttl
int ttl(const char *key)
Definition: Redis.h:177
Redis::hget
String hget(const char *key, const char *field)
Definition: Redis.cpp:74
Redis::pexpire_at
bool pexpire_at(const char *key, int timestamp)
Definition: Redis.h:162
Redis
Definition: Redis.h:55
Redis::stopSubscribing
void stopSubscribing()
Definition: Redis.h:280
Redis::RedisMsgErrorCallback
void(* RedisMsgErrorCallback)(Redis *, RedisMessageError)
Definition: Redis.h:60
Redis::subscribe
bool subscribe(const char *channel)
Definition: Redis.h:254
Redis::del
bool del(const char *key)
Definition: Redis.cpp:34
Redis::get
String get(const char *key)
Definition: Redis.cpp:29
Redis::startSubscribing
RedisSubscribeResult startSubscribing(RedisMsgCallback messageCallback, RedisMsgErrorCallback errorCallback=nullptr)
Definition: Redis.cpp:131
Redis::RedisMsgCallback
void(* RedisMsgCallback)(Redis *, String channel, String message)
Definition: Redis.h:58
Redis::unsubscribe
bool unsubscribe(const char *channelOrPattern)
Definition: Redis.cpp:119
Redis::expire_at
bool expire_at(const char *key, int timestamp)
Definition: Redis.h:145
Redis::pexpire
bool pexpire(const char *key, int ms)
Definition: Redis.h:153
Redis::publish
int publish(const char *channel, const char *message)
Definition: Redis.cpp:44
Redis::pttl
int pttl(const char *key)
Definition: Redis.h:185
Redis::persist
bool persist(const char *key)
Definition: Redis.cpp:59
Redis::lrange
std::vector< String > lrange(const char *key, int start, int stop)
Definition: Redis.cpp:99
Redis::authenticate
RedisReturnValue authenticate(const char *password)
Definition: Redis.cpp:4
Redis::hsetnx
bool hsetnx(const char *key, const char *field, const char *value)
Definition: Redis.h:203
Redis::exists
bool exists(const char *key)
Definition: Redis.cpp:49
Redis::hstrlen
int hstrlen(const char *key, const char *field)
Definition: Redis.cpp:89
Redis::hdel
bool hdel(const char *key, const char *field)
Definition: Redis.cpp:79
Redis::hexists
bool hexists(const char *key, const char *field)
Definition: Redis.cpp:94
Redis::Redis
Redis(Client &client)
Definition: Redis.h:67
Redis::append
int append(const char *key, const char *value)
Definition: Redis.cpp:39
Redis::hset
bool hset(const char *key, const char *field, const char *value)
Definition: Redis.h:194
Redis::psubscribe
bool psubscribe(const char *pattern)
Definition: Redis.h:259
Redis::set
bool set(const char *key, const char *value)
Definition: Redis.cpp:22
Redis::hlen
int hlen(const char *key)
Definition: Redis.cpp:84
Redis::expire
bool expire(const char *key, int seconds)
Definition: Redis.h:136