123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655 |
- #include "redis.h"
- #include <QThread>
- #include <QTimer>
- // void Test()
- //{
- // struct st
- // {
- // int a;
- // int b;
- // char c;
- // int d;
- // };
- // st t;
- // t.a = 1;
- // t.b = 2;
- // t.c = 'a';
- // t.d = 4;
- // const char *v[3];
- // size_t vlen[3];
- // v[0] = "set";
- // vlen[0] = strlen("set");
- // v[1] = "st";
- // vlen[1] = strlen("st");
- // v[2] = (const char *)&t;
- // vlen[2] = sizeof(struct st);
- // redisReply *r = (redisReply *)redisCommandArgv(rc, sizeof(v) / sizeof(v[0]), v, vlen);
- // r = (redisReply *)redisCommand(rc, "get st");
- // if (!r) {
- // printf("empty reply\n");
- // exit(1);
- // }
- // st *t2 = (st*)(r->str);
- // qDebug()<< "st2" << t2->a << t2->b << t2->c << t2->d;
- //}
- void getCallback(redisAsyncContext *ctx, void *r, void *privdata)
- {
- qDebug() << "getCallback called";
- redisReply *reply = static_cast<redisReply *>(r);
- if (reply == nullptr)
- {
- qDebug() << "The reply is nullptr";
- return;
- }
- for (int i = 0; i < reply->elements; i++)
- {
- qDebug() << "key: " << reply->element[i]->str;
- }
- if (QString(reply->element[0]->str) == "message") // 收到订阅消息
- {
- QString ch = QString(reply->element[1]->str);
- if (ch == "DevCh")
- {
- qDebug() << "devch...";
- // qDebug()<<"img:" << ++cnt;
- // QString js = QString(reply->element[2]->str);
- // QJsonObject jsonObj = QJsonDocument::fromJson(js.toLocal8Bit()).object(); //转成本地编码(utf-8), 中文正常
- // //quint32 type = jsonObj.value("type").toInt(); //toInt() 会丢数据
- // //qDebug()<<"type:" << type;
- // //QString base64Str = QString(reply->element[2]->str);
- // QString base64Str = jsonObj["img"].toString();
- // //qDebug()<<"str size:" << base64Str.size();
- // QPixmap baseimage;
- // baseimage.loadFromData(QByteArray::fromBase64(base64Str.toLatin1()));
- // QPixmap scaledPixmap = baseimage.scaled(500, 500, Qt::KeepAspectRatio); //设置图片大小并设置为按比例缩放
- // lab->setPixmap(scaledPixmap); //label放置图片并显示
- }
- else if (ch == "Alarm")
- {
- qDebug() << "alarm...";
- }
- else if (ch == "Led")
- {
- qDebug() << "led...";
- }
- }
- redisAsyncCommand(ctx, getCallback, nullptr, "blpop lTest 0");
- }
- void connectCallback(const redisAsyncContext *c, int status)
- {
- if (status != REDIS_OK)
- {
- qDebug("Error1: %s\n", c->errstr);
- // redisOk = false;
- return;
- }
- qDebug("Connected...\n");
- }
- void disconnectCallback(const redisAsyncContext *c, int status)
- {
- if (status != REDIS_OK)
- {
- qDebug("Error2: %s\n", c->errstr);
- // redisOk = false;
- return;
- }
- qDebug("Disconnected...\n");
- }
- EventSubInterface* g_pSubCB; // 订阅回调
- void RedisCB(redisAsyncContext *ctx, void *r, void *privdata)
- {
- redisReply *reply = static_cast<redisReply*>(r);
- if( reply->elements < 3)
- {
- return;
- }
- std::string type = reply->element[0]->str;
- if(strcasecmp(type.c_str(), "message") != 0)
- {
- return;
- }
- std::string chanel = reply->element[1]->str;
- std::string msg = reply->element[2]->str;
- if( g_pSubCB != nullptr )
- {
- g_pSubCB->SubCB((char*)chanel.c_str(), (char*)msg.c_str());
- }
- }
- Redis::Redis(QObject *parent) : QObject(parent)
- {
- redisOk = false;
- g_pSubCB = nullptr;
- // conn();
- }
- Redis::~Redis()
- {
- delete rc;
- delete rac;
- }
- void Redis::conn()
- {
- if (!redisOk) // 未连接
- {
- // 同步连接
- rc = redisConnect(ip.toUtf8(), port);
- if (rc == nullptr || rc->err)
- {
- qDebug() << "redis err:" << rc->errstr;
- }
- else
- {
- QString authCmd = "auth " + auth; // 认证
- redisReply *reply = (redisReply *)redisCommand(rc, authCmd.toUtf8());
- // qDebug()<< "auth:" << reply->str;
- if (QString::compare(reply->str, "OK"))
- {
- qDebug() << "redis connect fail.";
- }
- else
- {
- redisOk = true;
- qDebug() << "redis connect successfully.";
- }
- }
- }
- else
- {
- // qDebug()<< "~ ";
- }
- }
- void Redis::start()
- {
- conn();
- //开启一个定时器, 每秒检测一次是否断开, 断开后自动连接redis服务器
- QTimer *redisTimer = new QTimer();
- connect(redisTimer, SIGNAL(timeout()), this, SLOT(conn()));
- redisTimer->start(1000);
- }
- bool Redis::hset(QString k, QString f, QString v)
- {
- // 如果 field 是哈希表中的一个新建域,并且值设置成功,reply->integer为1
- // 如果哈希表中域 field 已经存在且旧值已被新值覆盖,reply->integer为0
- // 无法区别是否成功
- bool ret = false;
- redisReply *reply = (redisReply *)redisCommand(rc, "hset %s %s %s", k.toStdString().c_str(), f.toStdString().c_str(), v.toStdString().c_str()); // 支持空格
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else
- {
- // qDebug() <<"type:" << reply->type << reply->integer; //type = 3
- ret = true;
- }
- return ret;
- }
- QString Redis::hget(QString k, QString f)
- {
- QString ret;
- redisReply *reply = (redisReply *)redisCommand(rc, QString("hget " + k + " " + f).toStdString().c_str());
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else
- {
- // type:4表示不存在,type:1表示返回的为字符串
- // qDebug() <<"type:" << reply->type << reply->str << reply->len; //type:1
- if (reply->len)
- {
- ret = QString(reply->str);
- }
- }
- return ret;
- }
- QStringList Redis::hkeys(QString k)
- {
- QStringList ret;
- redisReply *reply = (redisReply *)redisCommand(rc, QString("hkeys " + k).toStdString().c_str());
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else if (reply->type == REDIS_REPLY_ARRAY)
- {
- // type:4表示不存在,type:1表示返回的为字符串
- // qDebug() <<"type:" << reply->type << reply->str << reply->len; //type:1
- for (size_t i = 0; i < reply->elements; i++)
- {
- // qDebug() << "key: " << i << reply->element[i]->str;
- ret.append(QString(reply->element[i]->str));
- }
- }
- return ret;
- }
- QStringList Redis::hvals(QString k)
- {
- QStringList ret;
- redisReply *reply = (redisReply *)redisCommand(rc, QString("hvals " + k).toStdString().c_str());
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else if (reply->type == REDIS_REPLY_ARRAY)
- {
- // type:4表示不存在,type:1表示返回的为字符串
- // qDebug() <<"type:" << reply->type << reply->str << reply->len; //type:1
- for (size_t i = 0; i < reply->elements; i++)
- {
- // qDebug() << "key: " << i << reply->element[i]->str;
- ret.append(QString(reply->element[i]->str));
- }
- }
- return ret;
- }
- QHash<QString, QString> Redis::hgetall(QString k)
- {
- QHash<QString, QString> ret;
- redisReply *reply = (redisReply *)redisCommand(rc, QString("hgetall " + k).toStdString().c_str());
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else if (reply->type == REDIS_REPLY_ARRAY)
- {
- // type:4表示不存在,type:1表示返回的为字符串
- // qDebug() <<"type:" << reply->type << reply->str << reply->len; //type:1
- for (size_t i = 0; i < reply->elements; i += 2)
- {
- // qDebug() << "key: " << i << reply->element[i]->str;
- ret.insert(QString(reply->element[i]->str), QString(reply->element[i + 1]->str));
- }
- }
- return ret;
- }
- // 向队列尾(右)部加入字符串数据
- bool Redis::rpush(QString lData, QString s)
- {
- bool ret = false;
- // redisReply * reply = (redisReply*)redisCommand(rc, QString("rpush " + lData + " " + js).toStdString().c_str());
- redisReply *reply = (redisReply *)redisCommand(rc, "rpush %s %s", lData.toStdString().c_str(), s.toStdString().c_str()); // 支持空格
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else
- {
- // qDebug() <<"type:" << reply->type << reply->integer; //type = 3
- // reply->integer为队列的个数,理论应该大于0
- if (reply->integer)
- {
- ret = true;
- }
- }
- return ret;
- }
- // 向队列尾(右)部加入二进制数据
- bool Redis::rpushb(QString lData, QByteArray ba)
- {
- bool ret = false;
- const char *arg[3]; // 3个参数(cmd, k, v)
- size_t vlen[3]; // 3个参数长度
- arg[0] = "rpush";
- vlen[0] = strlen("rpush");
- arg[1] = lData.toStdString().c_str();
- vlen[1] = lData.size();
- arg[2] = (const char *)ba.data();
- vlen[2] = ba.size();
- redisReply *reply = (redisReply *)redisCommandArgv(rc, sizeof(arg) / sizeof(arg[0]), arg, vlen);
- // redisReply * reply = (redisReply*)redisCommand(rc, QString("rpush " + lData + " " + js).toStdString().c_str());
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else
- {
- // qDebug() <<"type:" << reply->type << reply->integer; //type = 3
- // reply->integer为队列的个数,理论应该大于0
- if (reply->integer)
- {
- ret = true;
- }
- }
- return ret;
- }
- QString Redis::lpop(QString lData)
- {
- QString ret;
- redisReply *reply = (redisReply *)redisCommand(rc, QString("lpop " + lData).toStdString().c_str());
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else if (reply->len)
- {
- ret = QString(reply->str);
- }
- return ret;
- }
- // 阻塞从队列头部获取最早数据
- bool Redis::blpop(QString lData, redisCallbackFn *fn)
- {
- if (rac == nullptr)
- {
- // 异步连接
- rac = redisAsyncConnect(ip.toUtf8(), port);
- if (rac->err)
- {
- qDebug() << "error: " << rac->errstr;
- redisAsyncFree(rac);
- }
- else
- {
- adapter.setContext(rac);
- redisAsyncSetConnectCallback(rac, connectCallback);
- redisAsyncSetDisconnectCallback(rac, disconnectCallback);
- QString authCmd = "auth " + auth; // 认证
- redisAsyncCommand(rac, nullptr, nullptr, authCmd.toUtf8());
- qDebug() << "redis ok.";
- redisOk = true;
- }
- }
- if (rac && redisOk)
- {
- redisAsyncCommand(rac, fn, nullptr, ("blpop " + lData + " 0").toStdString().c_str());
- return true;
- }
- else
- {
- return false;
- }
- }
- // 同步阻塞一定时间返回数据
- QString Redis::blpop(QString lData, quint32 timeout)
- {
- // 最小为1,防止0时永久阻塞
- if (timeout < 1)
- {
- timeout = 1;
- }
- QString ret;
- redisReply *reply = (redisReply *)redisCommand(rc, QString("blpop " + lData + " " + QString::number(timeout)).toStdString().c_str());
- // for(int i = 0; i < reply->elements; i++){
- // qDebug() << "key: " << reply->element[i]->str;
- // }
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else if (reply->elements > 1)
- {
- ret = QString(reply->element[1]->str);
- }
- return ret;
- }
- bool Redis::set(QString k, QString v)
- {
- bool ret = false;
- // redisReply * reply = (redisReply*)redisCommand(rc, QString("set " + k + " " + v).toStdString().c_str()); //不支持空格
- redisReply *reply = (redisReply *)redisCommand(rc, "set %s %s", k.toStdString().c_str(), v.toStdString().c_str()); // 支持空格
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else
- {
- // qDebug() <<"type:" << reply->type << reply->str << reply->len; //type:5 str:OK len:2
- if (reply->type == 6)
- {
- qDebug() << "err:" << v;
- }
- // 返回OK为成功,长度2为str长度
- ret = true;
- }
- return ret;
- }
- bool Redis::setb(QString k, QByteArray &v)
- {
- bool ret = false;
- const char *arg[3]; // 3个参数(cmd, k, v)
- size_t vlen[3]; // 3个参数长度
- arg[0] = "set";
- vlen[0] = strlen("set");
- arg[1] = k.toStdString().c_str();
- vlen[1] = k.size();
- arg[2] = (const char *)v.data();
- vlen[2] = v.size();
- redisReply *reply = (redisReply *)redisCommandArgv(rc, sizeof(arg) / sizeof(arg[0]), arg, vlen);
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else
- {
- // qDebug() <<"type:" << reply->type << reply->str << reply->len; //type:5 str:OK len:2
- if (reply->type == 6)
- {
- qDebug() << "err:" << v;
- }
- // 返回OK为成功,长度2为str长度
- ret = true;
- }
- return ret;
- }
- QString Redis::get(QString k)
- {
- QString ret;
- redisReply *reply = (redisReply *)redisCommand(rc, QString("get " + k).toStdString().c_str());
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else if (reply->len)
- {
- ret = QString(reply->str);
- }
- return ret;
- }
- QByteArray Redis::getb(QString k)
- {
- QByteArray ret;
- redisReply *reply = (redisReply *)redisCommand(rc, QString("get " + k).toStdString().c_str());
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else if (reply->len)
- {
- ret = QByteArray(reply->str, reply->len); // 加上长度,保证二进制安全
- // qDebug()<< reply->len << ret.size();
- }
- return ret;
- }
- bool Redis::expire(QString k, int sec)
- {
- bool ret = false;
- redisReply *reply = (redisReply *)redisCommand(rc, QString("expire " + k + " " + QString::number(sec, 10)).toStdString().c_str());
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else
- {
- // qDebug() <<"type:" << reply->type << reply->integer; //type = 3
- // K不存在为0,存在为1
- if (reply->integer)
- {
- ret = true;
- }
- }
- return ret;
- }
- bool Redis::publish(QString ch, QString s)
- {
- bool ret = false;
- // redisReply * reply = (redisReply*)redisCommand(rc, QString("publish " + ch + " " + js).toStdString().c_str());
- redisReply *reply = (redisReply *)redisCommand(rc, "publish %s %s", ch.toStdString().c_str(), s.toStdString().c_str()); // 支持空格
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else
- {
- // qDebug() <<"type:" << reply->type << reply->integer; //type:3, integer:2
- // integer为2,不懂什么意思,这个用于实时,无需判断是否成功,连接正常即可
- ret = true;
- }
- return ret;
- }
- bool Redis::publishb(QString ch, QByteArray ba)
- {
- bool ret = false;
- const char *arg[3]; // 3个参数(cmd, k, v)
- size_t vlen[3]; // 3个参数长度
- arg[0] = "publish";
- vlen[0] = strlen("publish");
- arg[1] = ch.toStdString().c_str();
- vlen[1] = ch.size();
- arg[2] = (const char *)ba.data();
- vlen[2] = ba.size();
- redisReply *reply = (redisReply *)redisCommandArgv(rc, sizeof(arg) / sizeof(arg[0]), arg, vlen);
- // redisReply * reply = (redisReply*)redisCommand(rc, QString("publish " + ch + " " + js).toStdString().c_str());
- if (rc->err)
- {
- redisOk = false;
- qDebug() << rc->errstr;
- }
- else
- {
- qDebug() << "type:" << reply->type << reply->integer; // type:3, integer:2
- // integer为2,不懂什么意思,这个用于实时,无需判断是否成功,连接正常即可
- ret = true;
- }
- return ret;
- }
- void Redis::subscribe(QString ch, EventSubInterface *fn)
- {
- g_pSubCB = fn;
- if (rac == nullptr)
- {
- // 异步连接
- rac = redisAsyncConnect(ip.toUtf8(), port);
- if (rac->err)
- {
- qDebug() << "error: " << rac->errstr;
- redisAsyncFree(rac);
- }
- else
- {
- adapter.setContext(rac);
- redisAsyncSetConnectCallback(rac, connectCallback);
- redisAsyncSetDisconnectCallback(rac, disconnectCallback);
- QString authCmd = "auth " + auth; // 认证
- redisAsyncCommand(rac, nullptr, nullptr, authCmd.toUtf8());
- qDebug() << "redis ok.";
- redisOk = true;
- }
- }
- if (rac && redisOk)
- {
- redisAsyncCommand(rac, RedisCB, nullptr, QString("subscribe " + ch).toStdString().c_str());
- }
- }
- void Redis::psubscribe(QString ch, EventSubInterface *fn)
- {
- g_pSubCB = fn;
- if (rac == nullptr)
- {
- // 异步连接
- rac = redisAsyncConnect(ip.toUtf8(), port);
- if (rac->err)
- {
- qDebug() << "error: " << rac->errstr;
- redisAsyncFree(rac);
- }
- else
- {
- adapter.setContext(rac);
- redisAsyncSetConnectCallback(rac, connectCallback);
- redisAsyncSetDisconnectCallback(rac, disconnectCallback);
- QString authCmd = "auth " + auth; // 认证
- redisAsyncCommand(rac, nullptr, nullptr, authCmd.toUtf8());
- qDebug() << "redis ok.";
- redisOk = true;
- }
- }
- if (rac && redisOk)
- {
- redisAsyncCommand(rac, RedisCB, nullptr, QString("psubscribe " + ch).toStdString().c_str());
- }
- }
- void Redis::Setup(tagSetup ts)
- {
- ip = ts.addr.c_str();
- port = ts.port;
- auth = ts.password.c_str();
- redisOk = false;
- }
|