Arduino-Redis
A Redis library for Arduino.
Redis.cpp
Go to the documentation of this file.
1 #include "Redis.h"
2 #include "RedisInternal.h"
3 
4 RedisReturnValue Redis::authenticate(const char *password)
5 {
6  if (conn.connected())
7  {
8  int passwordLength = strlen(password);
9  if (passwordLength > 0)
10  {
11  auto cmdRet = RedisCommand("AUTH", ArgList{password}).issue(conn);
12  return cmdRet->type() == RedisObject::Type::SimpleString && (String)*cmdRet == "OK"
13  ? RedisSuccess
15  }
16 
17  return RedisSuccess;
18  }
19 
21 }
22 
23 #define TRCMD(t, c, ...) return RedisCommand(c, ArgList{__VA_ARGS__}).issue_typed<t>(conn)
24 
25 #define TRCMD_EXPECTOK(c, ...) (bool)(((String)*RedisCommand(c, ArgList{__VA_ARGS__}).issue(conn)).indexOf("OK") != -1)
26 
27 bool Redis::set(const char *key, const char *value)
28 {
29  return TRCMD_EXPECTOK("SET", key, value);
30 }
31 
32 String Redis::get(const char *key)
33 {
34  TRCMD(String, "GET", key);
35 }
36 
37 bool Redis::del(const char *key)
38 {
39  TRCMD(bool, "DEL", key);
40 }
41 
42 int Redis::append(const char *key, const char *value)
43 {
44  TRCMD(int, "APPEND", key, value);
45 }
46 
47 int Redis::publish(const char *channel, const char *message)
48 {
49  TRCMD(int, "PUBLISH", channel, message);
50 }
51 
52 bool Redis::exists(const char *key)
53 {
54  TRCMD(bool, "EXISTS", key);
55 }
56 
57 bool Redis::_expire_(const char *key, int arg, const char *cmd_var)
58 {
59  TRCMD(bool, cmd_var, key, String(arg));
60 }
61 
62 bool Redis::persist(const char *key)
63 {
64  TRCMD(bool, "PERSIST", key);
65 }
66 
67 int Redis::_ttl_(const char *key, const char *cmd_var)
68 {
69  TRCMD(int, cmd_var, key);
70 }
71 
72 bool Redis::_hset_(const char *key, const char *field, const char *value, const char *cmd_var)
73 {
74  TRCMD(int, cmd_var, key, field, value);
75 }
76 
77 String Redis::hget(const char *key, const char *field)
78 {
79  TRCMD(String, "HGET", key, field);
80 }
81 
82 bool Redis::hdel(const char *key, const char *field)
83 {
84  TRCMD(bool, "HDEL", key, field);
85 }
86 
87 int Redis::hlen(const char *key)
88 {
89  TRCMD(int, "HLEN", key);
90 }
91 
92 int Redis::hstrlen(const char *key, const char *field)
93 {
94  TRCMD(int, "HSTRLEN", key, field);
95 }
96 
97 bool Redis::hexists(const char *key, const char *field)
98 {
99  TRCMD(bool, "HEXISTS", key, field);
100 }
101 
102 std::vector<String> Redis::lrange(const char *key, int start, int stop)
103 {
104  auto rv = RedisCommand("LRANGE", ArgList{key, String(start), String(stop)}).issue(conn);
105  return rv->type() == RedisObject::Type::Array
106  ? (std::vector<String>)*((RedisArray *)rv.get())
107  : std::vector<String>();
108 }
109 
110 String Redis::lindex(const char *key, int index)
111 {
112  TRCMD(String, "LINDEX", key, String(index));
113 }
114 
115 int Redis::llen(const char *key)
116 {
117  TRCMD(int, "LLEN", key);
118 }
119 
120 String Redis::lpop(const char *key)
121 {
122  TRCMD(String, "LPOP", key);
123 }
124 
125 int Redis::lpos(const char *key, const char *element)
126 {
127  TRCMD(int, "LPOS", key, element);
128 }
129 
130 int Redis::lpush(const char *key, const char *value, bool exclusive)
131 {
132  TRCMD(int, (exclusive ? "LPUSHX" : "LPUSH"), key, value);
133 }
134 
135 int Redis::lrem(const char *key, int count, const char *element)
136 {
137  TRCMD(int, "LREM", key, String(count), element);
138 }
139 
140 bool Redis::lset(const char *key, int index, const char *element)
141 {
142  TRCMD_EXPECTOK("LSET", key, String(index), element);
143 }
144 
145 bool Redis::ltrim(const char *key, int start, int stop)
146 {
147  TRCMD_EXPECTOK("LTRIM", key, String(start), String(stop));
148 }
149 
150 String Redis::info(const char *section)
151 {
152  TRCMD(String, "INFO", (section ? section : ""));
153 }
154 
155 String Redis::rpop(const char *key)
156 {
157  TRCMD(String, "RPOP", key);
158 }
159 
160 int Redis::rpush(const char *key, const char *value, bool exclusive)
161 {
162  TRCMD(int, (exclusive ? "RPUSHX" : "RPUSH"), key, value);
163 }
164 
165 bool Redis::_subscribe(SubscribeSpec spec)
166 {
167  if (!subscriberMode)
168  {
169  subSpec.push_back(spec);
170  return true;
171  }
172 
173  const char *cmdName = spec.pattern ? "PSUBSCRIBE" : "SUBSCRIBE";
174  auto rv = RedisCommand(cmdName, ArgList{spec.spec}).issue(conn);
175  return rv->type() == RedisObject::Type::Array;
176 }
177 
178 bool Redis::unsubscribe(const char *channelOrPattern)
179 {
180  auto rv = RedisCommand("UNSUBSCRIBE", ArgList{channelOrPattern}).issue(conn);
181 
182  if (rv->type() == RedisObject::Type::Array)
183  {
184  auto vec = (std::vector<String>)*((RedisArray *)rv.get());
185  return vec.size() == 3 && vec[1] == String(channelOrPattern);
186  }
187 
188  return false;
189 }
190 
191 RedisSubscribeResult Redis::startSubscribing(RedisMsgCallback messageCallback, RedisMsgErrorCallback errCallback)
192 {
193  if (!messageCallback)
194  {
196  }
197 
198  bool success = true;
199  subscriberMode = true;
200  if (subSpec.size())
201  {
202  for (auto spec : subSpec)
203  {
204  success = _subscribe(spec) && success;
205  }
206  }
207 
208  if (!success)
209  {
211  }
212 
213  auto emitErr = [=](RedisMessageError errCode) -> bool {
214  if (errCallback)
215  {
216  errCallback(this, errCode);
217  }
218  };
219 
220  subLoopRun = true;
221  while (subLoopRun)
222  {
223  auto msg = RedisObject::parseType(conn);
224 
225  if (msg->type() == RedisObject::Type::InternalError)
226  {
227  auto errPtr = (RedisInternalError *)msg.get();
228 
229  if (errPtr->code() == RedisInternalError::Disconnected)
230  {
232  }
233 
235  }
236 
237  if (msg->type() != RedisObject::Type::Array)
238  {
240  continue;
241  }
242 
243  auto msgVec = (std::vector<String>)*((RedisArray *)msg.get());
244 
245  if (msgVec.size() < 3)
246  {
248  continue;
249  }
250 
251  if (msgVec[0] != "message" && msgVec[0] != "pmessage")
252  {
253  emitErr(RedisMessageUnknownType);
254  continue;
255  }
256 
257  // pmessage payloads have an extra paramter at index 1 that specifies the matched pattern; we ignore it here
258  auto pMsgAdd = msgVec[0] == "pmessage" ? 1 : 0;
259  messageCallback(this, msgVec[1 + pMsgAdd], msgVec[2 + pMsgAdd]);
260  }
261 
262  return RedisSubscribeSuccess;
263 }
Redis::lset
bool lset(const char *key, int index, const char *element)
Definition: Redis.cpp:140
RedisMessageError
RedisMessageError
Definition: Redis.h:54
Redis::hget
String hget(const char *key, const char *field)
Definition: Redis.cpp:77
RedisMessageBadResponseType
@ RedisMessageBadResponseType
The underlying Redis type detected in the message is not of the type expected.
Definition: Redis.h:57
RedisCommand
Definition: RedisInternal.h:154
Redis::del
bool del(const char *key)
Definition: Redis.cpp:37
RedisAuthFailure
@ RedisAuthFailure
The authentication credentials used are not valid.
Definition: Redis.h:36
Redis::lpush
int lpush(const char *key, const char *value, bool exclusive=false)
Definition: Redis.cpp:130
Redis::get
String get(const char *key)
Definition: Redis.cpp:32
RedisMessageUnknownType
@ RedisMessageUnknownType
An unknown error occurred.
Definition: Redis.h:61
RedisSuccess
@ RedisSuccess
Definition: Redis.h:32
Redis::startSubscribing
RedisSubscribeResult startSubscribing(RedisMsgCallback messageCallback, RedisMsgErrorCallback errorCallback=nullptr)
Definition: Redis.cpp:191
Redis::unsubscribe
bool unsubscribe(const char *channelOrPattern)
Definition: Redis.cpp:178
RedisSubscribeSetupFailure
@ RedisSubscribeSetupFailure
Setting up for subscription mode failed.
Definition: Redis.h:45
RedisSubscribeSuccess
@ RedisSubscribeSuccess
Definition: Redis.h:50
RedisInternalError::Disconnected
@ Disconnected
Definition: RedisInternal.h:136
RedisSubscribeResult
RedisSubscribeResult
Definition: Redis.h:40
Redis::publish
int publish(const char *channel, const char *message)
Definition: Redis.cpp:47
RedisMessageTruncatedResponse
@ RedisMessageTruncatedResponse
The message response was truncated early.
Definition: Redis.h:59
Redis::persist
bool persist(const char *key)
Definition: Redis.cpp:62
RedisArray
Definition: RedisInternal.h:90
Redis::lrange
std::vector< String > lrange(const char *key, int start, int stop)
Definition: Redis.cpp:102
RedisInternal.h
Redis::rpush
int rpush(const char *key, const char *value, bool exclusive=false)
Definition: Redis.cpp:160
RedisInternalError
Definition: RedisInternal.h:129
Redis::authenticate
RedisReturnValue authenticate(const char *password)
Definition: Redis.cpp:4
Redis::lpop
String lpop(const char *key)
Definition: Redis.cpp:120
RedisObject::parseType
static std::shared_ptr< RedisObject > parseType(Client &)
Definition: RedisInternal.cpp:131
TRCMD
#define TRCMD(t, c,...)
Definition: Redis.cpp:23
Redis::lpos
int lpos(const char *key, const char *element)
Definition: Redis.cpp:125
ArgList
std::vector< String > ArgList
Definition: RedisInternal.h:12
TRCMD_EXPECTOK
#define TRCMD_EXPECTOK(c,...)
Definition: Redis.cpp:25
RedisSubscribeOtherError
@ RedisSubscribeOtherError
An unknown error occurred.
Definition: Redis.h:49
RedisSubscribeBadCallback
@ RedisSubscribeBadCallback
One of the callback parameters given is invalid.
Definition: Redis.h:43
Redis::exists
bool exists(const char *key)
Definition: Redis.cpp:52
RedisNotConnectedFailure
@ RedisNotConnectedFailure
Authenticate attempted before the connection has been established.
Definition: Redis.h:34
Redis::lindex
String lindex(const char *key, int index)
Definition: Redis.cpp:110
Redis::hstrlen
int hstrlen(const char *key, const char *field)
Definition: Redis.cpp:92
Redis::hdel
bool hdel(const char *key, const char *field)
Definition: Redis.cpp:82
Redis.h
RedisSubscribeServerDisconnected
@ RedisSubscribeServerDisconnected
The remote end disconnected, retry may be available.
Definition: Redis.h:47
Redis::llen
int llen(const char *key)
Definition: Redis.cpp:115
Redis::hexists
bool hexists(const char *key, const char *field)
Definition: Redis.cpp:97
RedisReturnValue
RedisReturnValue
Definition: Redis.h:30
Redis::append
int append(const char *key, const char *value)
Definition: Redis.cpp:42
Redis::set
bool set(const char *key, const char *value)
Definition: Redis.cpp:27
Redis::rpop
String rpop(const char *key)
Definition: Redis.cpp:155
Redis::lrem
int lrem(const char *key, int count, const char *element)
Definition: Redis.cpp:135
Redis::info
String info(const char *section)
Definition: Redis.cpp:150
Redis::hlen
int hlen(const char *key)
Definition: Redis.cpp:87
Redis::ltrim
bool ltrim(const char *key, int start, int stop)
Definition: Redis.cpp:145